<?php

namespace App\Api\Http\Controllers;

use App\Application\UserService;
use App\Repositories\Eloquent\User\Entity\SocialiteUser;
use App\Repositories\User\UserRepositoryInterface;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Overtrue\Socialite\AuthorizeFailedException;
use Overtrue\Socialite\Providers\WeChatProvider;
use Overtrue\Socialite\SocialiteManager;
use Overtrue\Socialite\User;

class AuthController extends Controller
{
    /**
     * @var UserService
     */
    protected $user_service;

    public function __construct(UserService $user_service)
    {
        $this->user_service = $user_service;
    }

    /**
     * 微信登陆
     *
     * @param Request $request
     *
     * @return \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\RedirectResponse
     */
    public function wechat(Request $request)
    {
        $this->preLoginInit();

        $config = [
            'wechat' => [
                'client_id'     => config('wechat.app_id'),
                'client_secret' => config('wechat.secret'),
                'redirect'      => '',
            ],
        ];
        $socialite = new SocialiteManager($config, $request);
        /** @var WeChatProvider $wechat */
        $wechat = $socialite->driver('wechat');

        if ($request->has('code') && $request->has('state')) {
            /** @var User $user */
            $user = $this->getWechatUser($wechat, $request); // 拿到授权用户资料
            if ($user) {
                $socialite_user = $this->createSocialiteUser($user);

                //获取登陆code
                $code = $this->user_service->getLoginCode($socialite_user);

                return redirect()->to($this->getAuthSuccessRedirectUrl($code));
            }
        }

        return $wechat->scopes(['snsapi_userinfo'])->redirect($request->url());
    }


    /**
     * 获取微信授权的用户信息
     *
     * @param WeChatProvider $wechat
     * @param Request        $request
     *
     * @return \Overtrue\Socialite\User
     */
    private function getWechatUser(WeChatProvider $wechat, Request $request)
    {
        /** @var User $user */
        try {
            $user = $wechat->user(); // 拿到授权用户资料
            $data = $user->getOriginal();
            if (isset($data['errcode'])) {
                \Log::debug('SocialiteUser data = ' . print_r($user, true));
                throw new AuthorizeFailedException('getUserByTokenError :' . $data['errmsg'], json_encode($data));
            }

            return $user;
        } catch (AuthorizeFailedException $e) {
            \Log::error('AuthorizeFailedException: ' . $e->getMessage() . ' in file' . __FILE__ . ' ' . __LINE__);

            $key = md5($request->ip() . '|' . $request->header('User-Agent'));
            if (!app('cache')->has($key)) {
                app('cache')->put($key, 1, Carbon::now()->addMinute());
            } else {
                app('cache')->increment($key);
            }

            if (app('cache')->get($key) > 3) {
                \Log::error('AuthorizeFailedException error count = ' . app('cache')->get($key));
                throw $e;
            }
        }
    }

    /**
     * Create socialite user entity.
     *
     * @param User $user
     *
     * @return SocialiteUser
     */
    protected function createSocialiteUser(User $user)
    {
        $socialite_user = new SocialiteUser();
        $socialite_user->name = $user->getName();
        $socialite_user->nick_name = $user->getNickname();
        $socialite_user->email = (string)$user->getEmail();
        $socialite_user->avatar = $user->getAvatar();
        $socialite_user->params = $user->getOriginal();
        $socialite_user->device_type = app('client')->device_type;
        $socialite_user->ip = (string)app('client')->ip;

        //是否存在邀请人
        if (app('client')->invite_uid > 0) {
            $user_repository = app(UserRepositoryInterface::class);
            $inviter = $user_repository->showByUid(app('client')->invite_uid);
            if ($inviter) {
                $socialite_user->invite_uid = $inviter->id;
            }
        }

        $socialite_user->uid = $user->getOriginal()['unionid'];
        $socialite_user->open_id = $user->getId();

        return $socialite_user;
    }

    /**
     * 登陆成功后跳转的地址
     *
     * @param $code
     *
     * @return string
     */
    private function getAuthSuccessRedirectUrl($code)
    {
        $redirect_url = session('auth_redirect_url', env('H5_URL') . '/token');
        session()->remove('auth_redirect_url');

        if (strpos($redirect_url, 'code=') > 0) {
            $redirect_url = preg_replace('/code\=\w+\&?/', '', $redirect_url);
        }

        if (strpos($redirect_url, '?') > 0) {
            return $redirect_url . '&code=' . $code;
        }

        return $redirect_url . '?code=' . $code;
    }

    /**
     * 登录前的初始化
     */
    private function preLoginInit()
    {
        //登陆成功需要跳转页面地址
        if (($redirect_url = request()->get('redirect_url')) != '') {
            if (url()->isValidUrl($redirect_url) && strpos($redirect_url, '/auth/') === false) {
                session()->put('auth_redirect_url', $redirect_url);
            }
        }

        //邀请人
        $this->inviter();
    }

    /**
     * 邀请人
     */
    private function inviter()
    {
        //邀请人
        $invite_uid = (int)request()->get('invite_uid');
        $session_invite_key = 'user_invite_uid';
        if ($invite_uid > 0) {
            session()->put($session_invite_key, $invite_uid);
        } else {
            $invite_uid = (int)session()->get($session_invite_key);
        }

        app('client')->setInviteUid($invite_uid);
    }
}
